#include "ServerManager.h"
#include "IdManager.h"
#include "msg_gate.h"
#include "msg_msgid.h"
#include "Utils.h"
#include "Hall.h"
using namespace SGLib;
using namespace std;

SINGLETON_CLASS_INIT(CServerManager);
SINGLETON_CLASS_INIT(CServiceExManager);

bool CServerManager::Init(u64 sid, bool delayConnect, bool checkAlive, u64 idfrom)
{
    m_sid = sid;
    m_delayConnect = delayConnect;
    m_checkAlive = checkAlive;
    m_global = NULL;
    m_config = NULL;
    m_service = NULL;
    if( !_InitGlobalConfig(m_sid, &m_global, &m_config) )
    {
        return false;
    }

    _SigHandle();
    
    CSessionManager::Instance();
    CIdManager::Instance().Init( idfrom );
    
    LOG_INIT( m_config->LogFile().c_str(), 
        m_config->_cl.getLogRollingMode(),
        m_config->_cl.getLogLevelMin(), 
        m_config->_cl.getLogLevelMax() );

    CSessionBase::m_aliveInterval = m_config->_cs._HeartBeatTime;
    CRpcSessionBase::m_aliveInterval = m_config->_cs._HeartBeatTime;

    return true;
}

void CServerManager::Stop()
{
    StopServiceEx<1>();
    m_service = NULL;
    LOG_INFO( "[%s][%s][%d] StopServiceEx", __FILE__, __FUNCTION__, __LINE__ );
}

u64 CServerManager::GetId()
{
    return m_sid;
}

void CServerManager::CheckSessionAliveTimerCallBack(void *data, s32 len)
{
    if( !data )
    {
        LOG_ERROR( "[%s][%s][%d] NULL data.", __FILE__, __FUNCTION__, __LINE__ );
        return;
    }

    TimerData *td = (TimerData*)data;
    CServerManager *mgr = (CServerManager*)td->data;
    mgr->_DoCheckSessionAlive();
}

SGLib::IPacketParser* CServerManager::GetPacketParser()
{
    if( m_service )
    {
        return m_service->GetPacketParser();
    }
    return NULL;
}

void CServerManager::ReloadServerConfig()
{
    if( m_global )
    {
        ServerConfig *cfg = m_global->ReloadServerConfig( GetId() );
        if( cfg )
        {
            m_config = cfg;
            s32 minlevel = m_config->_cl.getLogLevelMin();
            s32 maxlevel = m_config->_cl.getLogLevelMax();
            LOG_INFO( "[%s][%s][%d] reset log level[%d-%d]", 
                __FILE__, __FUNCTION__, __LINE__, minlevel, maxlevel );
            LOG_LEVEL_SET( minlevel, maxlevel );
        }
    }
}

void CServerManager::CloseSession(u64 sessionid)
{
    CSessionBase *client = CSessionManager::Instance().FindSession( sessionid );
    if( !client )
    {
        LOG_ERROR( "[%s][%s][%d] not find session[%llu]", __FILE__, __FUNCTION__, __LINE__, sessionid );
        return;
    }
    LOG_INFO( "[%s][%s][%d] session[%llu]", __FILE__, __FUNCTION__, __LINE__, sessionid );
    client->Close();
}

void CServerManager::SendMsgToServer(u64 serverid, u32 msgid, const IMessage &msg)
{
    CSessionBase *server = CSessionManager::Instance().FindServer( serverid );
    if( !server )
    {
        LOG_ERROR( "[%s][%s][%d] not find server[%llu]", 
                __FILE__, __FUNCTION__, __LINE__, serverid );
        return;
    }

    if( !server->SendMsg(msgid, msg) )
    {
        LOG_ERROR( "[%s][%s][%d] send to serverid[%llu] failed", 
            __FILE__, __FUNCTION__, __LINE__, serverid );
    }
}

void CServerManager::SendMsgToServers(std::vector<u64> &servers, u32 msgid, const IMessage &msg)
{
    std::vector<u64>::iterator it = servers.begin();
    for( ; it != servers.end(); ++it )
    {
        SendMsgToServer( *it, msgid, msg );
    }
}

void CServerManager::BroadcastToServers(u32 msgid, const IMessage &msg)
{
    std::vector<CSessionBase*> servers;
    CSessionManager::Instance().DumpServers( servers );
    std::vector<CSessionBase*>::iterator it = servers.begin();
    for( ; it != servers.end(); ++it )
    {
        if( !(*it)->SendMsg(msgid, msg) )
        {
            LOG_ERROR( "[%s][%s][%d] send to serverid[%llu] failed", 
                __FILE__, __FUNCTION__, __LINE__, (*it)->GetServerId() );
        }
    }
}
    
void CServerManager::SendMsgToRpcServer(u64 serverid, u32 msgid, const IMessage &msg)
{
    CConnSession *server = CSessionManager::Instance().FindRpcServer( serverid );
    if( !server )
    {
        LOG_ERROR( "[%s][%s][%d] not find server[%llu] msg[%u]", 
                __FILE__, __FUNCTION__, __LINE__,
                serverid, msgid );
        return;
    }
    server->SendMsg( msgid, msg );
}

void CServerManager::SendMsgToRpcServerWithHead(u64 serverid, u32 msgid, const IMessage &msg, char *head, int len)
{
    CConnSession *server = CSessionManager::Instance().FindRpcServer( serverid );
    if( !server )
    {
        LOG_ERROR( "[%s][%s][%d] not find server[%llu] msg[%u]", 
                __FILE__, __FUNCTION__, __LINE__,
                serverid, msgid );
        return;
    }
    server->SendMsgWithHead( msgid, msg, head, len );
}

void CServerManager::SendMsgToRpcServers(std::vector<u64> &servers, u32 msgid, const IMessage &msg)
{
    std::vector<u64>::iterator it = servers.begin();
    for( ; it != servers.end(); ++it )
    {
        SendMsgToRpcServer( *it, msgid, msg );
    }
}

void CServerManager::BroadcastToRpcServers(u32 msgid, const IMessage &msg)
{
    std::vector<CConnSession*> rpcServers;
    CSessionManager::Instance().DumpRpcServers( rpcServers );
    std::vector<CConnSession*>::iterator it = rpcServers.begin();
    for( ; it != rpcServers.end(); ++it )
    {
        (*it)->SendMsg( msgid, msg );
    }
}

void CServerManager::SendMsgToSession(u64 sessionid, const char *msg, s32 len)
{
    CSessionBase *client = CSessionManager::Instance().FindSession( sessionid );
    if( !client )
    {
        LOG_ERROR( "[%s][%s][%d] not find sessoin[%llu]", 
                __FILE__, __FUNCTION__, __LINE__, sessionid );
        return;
    }

    if( !client->Send((const byte*)msg, len) )
    {
        LOG_ERROR( "[%s][%s][%d] send to session[%llu] failed", 
                __FILE__, __FUNCTION__, __LINE__, sessionid );
    }
}

void CServerManager::SendMsgToSession(u64 sessionid, u32 msgid, const IMessage &msg)
{
    CSessionBase *client = CSessionManager::Instance().FindSession( sessionid );
    if( !client )
    {
        LOG_ERROR( "[%s][%s][%d] not find sessoin[%llu]", 
                __FILE__, __FUNCTION__, __LINE__, sessionid );
        return;
    }

    if( !client->SendMsg(msgid, msg) )
    {
        LOG_ERROR( "[%s][%s][%d] send to session[%llu] failed", 
                __FILE__, __FUNCTION__, __LINE__, sessionid );
    }
}

void CServerManager::SendMsgToSessions(std::vector<u64> &sessionids, u32 msgid, const IMessage &msg)
{
    std::vector<u64>::iterator it = sessionids.begin();
    for( ; it != sessionids.end(); ++it )
    {
        SendMsgToSession( *it, msgid, msg );
    }
}

void CServerManager::BroadcastToSessions(u32 msgid, const IMessage &msg)
{
    std::vector<CSessionBase*> sessions;
    CSessionManager::Instance().DumpSessions( sessions );
    std::vector<CSessionBase*>::iterator it = sessions.begin();
    for( ; it != sessions.end(); ++it )
    {
        if( !(*it)->SendMsg(msgid, msg) )
        {
            LOG_ERROR( "[%s][%s][%d] send to sessionid[%llu] failed", 
                __FILE__, __FUNCTION__, __LINE__, (*it)->GetSessionId() );
        }
    }
}

s32 CServerManager::AddTimer(u32 elapse, CallBackFunc callback, void *data, s32 len, bool persist)
{
    if( m_service )
    {
        return m_service->AddTimer( elapse, callback, data, len, persist );
    }
    return SGLib::CTimer<Timer_Count>::E_Invalid_TimerId;
}

void CServerManager::DelTimer(s32 timerid)
{
    if( m_service )
    {
        m_service->DelTimer( timerid );
    }
}

void CServerManager::SendMsg2Client(u64 gateid, u64 sessionid, u32 msgid, const IMessage &msg)
{
    vector<u64> sids;
    sids.push_back( sessionid );
    SendMsg2Clients( gateid, sids, msgid, msg );
}

void CServerManager::SendMsg2Clients(u64 gateid, std::vector<u64> &sessionids, u32 msgid, const IMessage &msg)
{
    gateproto::ServerGateMsg2Client m;
    m.clientid = sessionids;
    
    IPacketParser *parser = GetPacketParser();
    SELF_ASSERT( parser, return; );
    
    CHECK_SERIALIZE_MSG(msgid, msg, parser, return;);
    m.msg.append( msgbuffer, msglen );

    SendMsgToServer( gateid, msgid::SG_MSG_2_CLIENT, m );
}

#ifdef _USE_CURL_
void CServerManager::PostRequest(const std::string &url, const std::string &postdata, postRspCallback rspfunc, void *data, s32 len, s32 timeOut)
{
    if( m_service )
    {
        m_service->PostRequest( url, postdata, timeOut, rspfunc, data, len );
    }
}
#endif

void CServerManager::_DoCheckSessionAlive()
{
    CSessionManager::Instance().CheckSessionAlive();
}

bool CServerManager::_InitGlobalConfig(u64 sid, CGlobalConfig **global, ServerConfig **config)
{
    *config = NULL;
    *global = NULL;
    *global = new CGlobalConfig();
    if( *global == NULL )
    {
        printf( "[%s][%s][%d] ERROR\n", __FILE__, __FUNCTION__, __LINE__ );
        return false;
    }
    if( !((*global)->Load("config.xml")) )
    {
        printf( "[%s][%s][%d] ERROR\n", __FILE__, __FUNCTION__, __LINE__ );
        return false;
    }
    *config = (*global)->FindServerConfig( sid );
    if( *config == NULL )
    {
        printf( "[%s][%s][%d] ERROR\n", __FILE__, __FUNCTION__, __LINE__ );
        return false;
    }

    return true;
}

void CServerManager::_StartCheckSessionAlive()
{
    LOG_WARN( "[%s][%s][%d] every [%d]ms", __FILE__, __FUNCTION__, __LINE__, CheckSessionAlive_Timer );

    if( m_service )
    {
        TimerData data;
        data.data = this;
        s32 timerid = m_service->AddTimer(
                CheckSessionAlive_Timer, CheckSessionAliveTimerCallBack, &data, sizeof(TimerData), true );
        if( timerid == -1 )
        {
            LOG_ERROR( "[%s][%s][%d] AddTimer failed.", __FILE__, __FUNCTION__, __LINE__ );
        }
    }
    else
    {
        LOG_ERROR( "[%s][%s][%d] service NULL", __FILE__, __FUNCTION__, __LINE__ );
    }
}

void CServerManager::_InitRpcServers()
{
    SGLib::IPacketParser *parser = GetPacketParser();
    SELF_ASSERT( parser, return; );

    map<s32, char> usedType;
    std::vector<ConfigItem>::iterator it = GetServerConfig()->_cc._items.begin();
    for( ; it != GetServerConfig()->_cc._items.end(); ++it )
    {   
        for( u64 id=it->_IdFrom; id<=it->_IdTo; ++id )
        {   
            ServerConfig *sc = GetGlobalConfig()->FindServerConfig( id );
            SELF_ASSERT( sc, continue; );

            CSessionManager::Instance().AddRpcServer( id, sc->_cs._Ip.c_str(), sc->_cs._Port, parser );
        }   
    } 
}

void SigUsr_Handler(int sig)
{
    IServiceEx *m_service = CServiceExManager::Instance().GetServiceEx();
    m_service->DoWork(CHall::ReLoadGameConfig, NULL, 0);
}

void CServerManager::_SigHandle()
{
    struct sigaction act;        
    act.sa_handler = SigUsr_Handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    sigaction(SIGUSR1, &act, NULL);
}

void CServerManager::SignalMask()
{
    sigset_t    mask;
    sigemptyset(&mask);
    sigaddset(&mask, SIGUSR1);
    pthread_sigmask( SIG_BLOCK, &mask, NULL );
}


